import re

from django_redis import get_redis_connection
from rest_framework import serializers

from users.models import User, Address


class UserSerializer(serializers.ModelSerializer):
    """用户序列化器类"""
    password2 = serializers.CharField(label='重复密码', write_only=True)  # 默认的write_only是Fault
    sms_code = serializers.CharField(label='短信验证码', write_only=True)
    allow = serializers.CharField(label='是否同意协议', write_only=True)
    token = serializers.CharField(label='JWT token', read_only=True)

    class Meta:
        model = User
        fields = ('id', 'username', 'password', 'mobile', 'password2', 'sms_code', 'allow', 'token')
        # 添加额外限制条件
        extra_kwargs = {
            'username': {
                'min_length': 5,
                'max_length': 20,
                'error_messages': {
                    'min_length': '仅允许5-20个字符的用户名',
                    'max_length': '仅允许5-20个字符的用户名',
                }
            },
            'password': {
                'write_only': True,
                'min_length': 8,
                'max_length': 20,
                'error_messages': {
                    'min_length': '仅允许8-20个字符的密码',
                    'max_length': '仅允许8-20个字符的密码',
                }
            }
        }

    def validate_mobile(self, value):
        # 手机号格式
        if not re.match(r'^1[3-9]\d{9}$', value):
            raise serializers.ValidationError('手机号格式不正确')

        # 验证手机号是否注册过
        count = User.objects.filter(mobile=value).count()
        if count > 0:
            raise serializers.ValidationError('手机号已存在')
        return value

    def validate_allow(self, value):
        # 是否同意协议
        if value != 'true':
            raise serializers.ValidationError('请同意协议')
        return value

    def validate(self, attrs):
        """attrs： 字典，客户端传递的所有数据"""

        # 查看两次密码是否一致
        password = attrs['password']
        password2 = attrs['password2']

        if password != password2:
            raise serializers.ValidationError('两次输入的密码不一致')

        # 短信验证码验证
        mobile = attrs['mobile']

        # 获取redis链接
        redis_conn = get_redis_connection('verify_codes')
        real_sms_code = redis_conn.get('sms_%s' % mobile)  # 这里得到是bytes类型
        if real_sms_code is None:
            raise serializers.ValidationError('验证码已过期')
        sms_code = attrs['sms_code']  # 字符串类型
        # if sms_code != real_sms_code.decode():
        if real_sms_code.decode() != sms_code:
            raise serializers.ValidationError('短信验证码错误')

        return attrs

    # 创建新用户　默认的 Serializer.Model 中的密码字段不加密明文，所以我们要重写创建用户函数
    def create(self, validated_data):
        """validated_data　字典　校验之后的数据"""

        # 移除无用的数据
        del validated_data['password2']
        del validated_data['sms_code']
        del validated_data['allow']

        user = User.objects.create_user(**validated_data)
        # 服务器生成一个jwt token的字符串：保留用户的身份信息
        from rest_framework_jwt.settings import api_settings

        # 生成payload的方法  载荷
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        # 给user增加token属性，保存jwt token的信息
        user.token = token

        return user


class AddressSerializer(serializers.ModelSerializer):
    """地址序列化器类"""
    province_id = serializers.IntegerField(label='省id')
    city_id = serializers.IntegerField(label='市id')
    district_id = serializers.IntegerField(label='区id')
    province = serializers.StringRelatedField(label='省')
    city = serializers.StringRelatedField(label='市')
    district = serializers.StringRelatedField(label='区')

    class Meta:
        model = Address
        # fields = ('id', 'title', 'receiver', 'place', 'mobile', 'tel', 'email',
        #           'province', 'city', 'district', 'province_id', 'city_id', 'district_id')

        exclude = ('user', 'is_deleted', 'create_time', 'update_time')

    # 手机号格式
    def validate_mobile(self, value):
        if not re.match(r'^1[3-9]\d{9}$', value):
            raise serializers.ValidationError('手机号格式错误')

        return value

    def create(self, validated_data):
        """
        validated_data: 校验之后的数据，不包含user对象
        """
        # 获取登录用户user
        user = self.context['request'].user

        # 保存新增地址的数据
        validated_data['user'] = user

        # 调用`ModelSerializer`中的create进行新增地址创建
        return super().create(validated_data)


class AddressTitleSerializer(serializers.ModelSerializer):
    """地址标题的序列化器类"""
    class Meta:
        model = Address
        fields = ('title', )


